page_alloc: Hold heap_lock while adjusting page states to/from PGC_state_free.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 13 Sep 2010 16:08:31 +0000 (17:08 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 13 Sep 2010 16:08:31 +0000 (17:08 +0100)
This avoids races with buddy-merging logic in free_heap_pages().

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/common/page_alloc.c

index ed2dc1d599c9b74bc27d5db2ed8b58175f34894a..257f6bcf91287a65db49b3ba2b39585cfc60abb6 100644 (file)
@@ -415,8 +415,6 @@ static struct page_info *alloc_heap_pages(
     if ( d != NULL )
         d->last_alloc_node = node;
 
-    spin_unlock(&heap_lock);
-
     cpus_clear(mask);
 
     for ( i = 0; i < (1 << order); i++ )
@@ -438,6 +436,8 @@ static struct page_info *alloc_heap_pages(
         page_set_owner(&pg[i], NULL);
     }
 
+    spin_unlock(&heap_lock);
+
     if ( unlikely(!cpus_empty(mask)) )
     {
         perfc_incr(need_flush_tlb_flush);
@@ -533,6 +533,8 @@ static void free_heap_pages(
     ASSERT(order <= MAX_ORDER);
     ASSERT(node >= 0);
 
+    spin_lock(&heap_lock);
+
     for ( i = 0; i < (1 << order); i++ )
     {
         /*
@@ -560,8 +562,6 @@ static void free_heap_pages(
             pg[i].tlbflush_timestamp = tlbflush_current_time();
     }
 
-    spin_lock(&heap_lock);
-
     avail[node][zone] += 1 << order;
     total_avail_pages += 1 << order;